home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr11 / pctv4n2.zip / TELBOOK.C < prev    next >
C/C++ Source or Header  |  1993-06-09  |  8KB  |  359 lines

  1. /***************************************************************
  2.  *                                                             *
  3.  * TELBOOK1.C -                                                *
  4.  * Example using base 40 compression/decompression routines    *
  5.  * by Al Williams                                              *
  6.  *                                                             *
  7.  ***************************************************************/
  8.  
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <malloc.h>
  12. #include <conio.h>
  13. #include <ctype.h>
  14. #include <stdlib.h>
  15. #include "b40.h"
  16.  
  17. /* main table of phone numbers - 1000 maximum */
  18. struct phentry
  19.   {
  20.   char *text;
  21.   unsigned char siz;
  22.   } phonelst[1000];
  23.  
  24. /* first free entry in phonelst */
  25. int last=0;
  26.  
  27. /* buffers for input and conversion */
  28. char inbuf[81];
  29. char cvtbuf[81];
  30.  
  31. int menu(char *fn);
  32. void sdelete(char *p);
  33. void linein(char *inbuf,size_t siz,FILE *f);
  34. /* command functions */
  35. void list(FILE *f);
  36. void disp(FILE *f,int i,char *cvtbuf);
  37. void new(int id);
  38. void save(char *fn);
  39. void sdelete(char *p);
  40. void replace(void);
  41. void find(void);
  42. void telsort(void);
  43.  
  44.  
  45. /********************************************/
  46.  
  47. main(int argc,char *argv[])
  48.   {
  49.   FILE *f;
  50.   if (argc>2||argv[1][0]=='?'||argv[1][1]=='?')
  51.     {
  52.     printf("TELBOOK by Al Williams\n");
  53.     printf("usage: TELBOOK phonefile\n");
  54.     exit(1);
  55.     }
  56. /* open file */
  57.   f=fopen(argv[1],"rb");
  58. /* if data file present,  read it in */
  59.   if (f)
  60.     {
  61.     unsigned int n;
  62.     while (!feof(f))
  63.       {
  64. /* read count */
  65.       n=getc(f);
  66.       if (n==(unsigned int)EOF) break;
  67. /* read string in */
  68.       fread(inbuf,1,n,f);
  69. /* allocate space and copy it in */
  70.       phonelst[last].siz=n;
  71.       phonelst[last].text=malloc(n);
  72.       memcpy(phonelst[last++].text,inbuf,n);
  73.       }
  74.     fclose(f);
  75.     }
  76.   while (1) menu(argv[1]);
  77.   }
  78.  
  79. /****************** main menu */
  80. int menu(char *fn)
  81.   {
  82.   int cmd;
  83.   printf("   -- MAIN MENU --\n"
  84.          "L - List phone book\n"
  85.          "P - Print phone book\n"
  86.          "N - New entry\n"
  87.          "R - Replace entry\n"
  88.          "F - Find entry\n"
  89.          "S - Save phone book\n"
  90.          "O - Order (sort) phone book\n"
  91.          "X - eXit\nYour choice: ");
  92.   cmd=getch();
  93.   if (!cmd) { getch(); return; }
  94.   putch(cmd);
  95.   putch('\n');
  96.   putch('\r');
  97.   switch (toupper(cmd))
  98.     {
  99.     case 'L': list(stdout);
  100.               break;
  101.  
  102.     case 'P':
  103.               list(stdprn);
  104.               break;
  105.  
  106.     case 'N': new(-1);
  107.               break;
  108.  
  109.     case 'S': save(fn);
  110.               break;
  111.  
  112.     case 'R': replace();
  113.               break;
  114.  
  115.     case 'F': find();
  116.               break;
  117.  
  118.     case 'O': telsort();
  119.               break;
  120.  
  121.     case 'X': exit(0);
  122.     }
  123.   return;
  124.   }
  125.  
  126. /********************************************
  127. /* Read a line in -- shift to upper and strip the \n and process out
  128.    ( ) and -. Also, eat blanks after a ) character */
  129. void linein(char *inbuf,size_t siz,FILE *f)
  130.   {
  131.   char *p;
  132.   fflush(f);
  133.   fgets(inbuf,siz,f);
  134. /* remove \n at end if present */
  135.   p=strchr(inbuf,'\n');
  136.   if (p) *p='\0';
  137. /* shift to upper case */
  138.   strupr(inbuf);
  139. /* remove ( */
  140.   while (p=strchr(inbuf,'(')) sdelete(p);
  141. /* remove ) and trailing blanks */
  142.   while (p=strchr(inbuf,')'))
  143.     {
  144.     sdelete(p);
  145.     while (isspace(*p)) sdelete(p);
  146.     }
  147. /* remove - */
  148.   while (p=strchr(inbuf,'-')) sdelete(p);
  149.   }
  150.  
  151. /********************************************
  152. /* list all entries to file f */
  153. void list(FILE *f)
  154.   {
  155.   int i;
  156.   int total=0;
  157.   for (i=0;i<last;i++)
  158.     {
  159. /* decode line */
  160.     b40_decode(cvtbuf,phonelst[i].text,phonelst[i].siz);
  161.     total+=strlen(cvtbuf);
  162. /* call disp to print it out */
  163.     disp(f,i,cvtbuf);
  164.     }
  165.   fprintf(f,"%d bytes\n",total);
  166.   }
  167.  
  168. /********************************************
  169. /* Print line number i (decoded in cvtbuf) to file f */
  170. void disp(FILE *f,int i,char *cvtbuf)
  171.     {
  172.     char *token=NULL,telno[33],*tp=telno;
  173.     int l;
  174. /* print entry number */
  175.     fprintf(f,"[%03d] ",i);
  176. /* get tokens */
  177.     while (token=strtok(token?NULL:cvtbuf," \t"))
  178.       {
  179.       int l=strlen(token);
  180. /* if token is number -- try to format it as a phone number */
  181.       if (strspn(token,"0123456789")==l)
  182.         {
  183. /* if l==10 then (XXX) YYY-ZZZZ */
  184.         if (l==10)
  185.           {
  186.           *tp++='(';
  187.           memcpy(tp,token,3);
  188.           *(tp+=3)=')';
  189.           *(++tp)=' ';
  190.           tp++;
  191.           token+=3;
  192.           }
  193. /* if l==7 then YYY-ZZZZ */
  194.         if (l==10||l==7)
  195.           {
  196.           memcpy(tp,token,3);
  197.           *(tp+=3)='-';
  198.           strcpy(++tp,token+3);
  199. /* print formatted telephone number and get new token */
  200.           fprintf(f,"%s ",telno);
  201.           continue;
  202.           }
  203.         }
  204. /* print non-phone number tokens */
  205.       fprintf(f,"%s ",token);
  206.       }
  207.     putc('\n',f);
  208.     return;
  209.     }
  210.  
  211.  
  212.  
  213. /********************************************
  214. /* make new entry if id==-1 then add to end
  215.    else replace entry #id. If id is past
  216.    end, then pretend id==-1 */
  217. void new(int id)
  218.   {
  219.   char *p;
  220.   int n,c;
  221.   if (id>=last) id=-1;
  222. /* if replacing, confirm */
  223.   if (id!=-1)
  224.     {
  225. /* print entry to replace */
  226.     b40_decode(cvtbuf,phonelst[id].text,phonelst[id].siz);
  227.     disp(stdout,id,cvtbuf);
  228. /* prompt */
  229.     printf("Change this entry (Y/N): ");
  230.     do
  231.       {
  232.       c=getche();
  233.       if (!c)
  234.         {
  235.         getch();
  236.         continue;
  237.         }
  238.       c=toupper(c);
  239.       } while (c!='N'&&c!='Y');
  240.     putchar('\n');
  241. /* if no confirm, quit */
  242.     if (c=='N') return;
  243.     }
  244. /* if previous entry exists, free its memory */
  245.   if (id!=-1&&phonelst[id].text) free(phonelst[id].text);
  246. /* get new entry */
  247.   printf("New Entry:\n");
  248.   linein(inbuf,sizeof(inbuf),stdin);
  249.  
  250. /* encode entry */
  251.   n=b40_encode(cvtbuf,inbuf);
  252. /* enter into table */
  253.   phonelst[id==-1?last:id].siz=n;
  254.   phonelst[id==-1?last:id].text=malloc(n);
  255.   memcpy(phonelst[id==-1?last++:id].text,cvtbuf,n);
  256.   }
  257.  
  258. /********************************************
  259. /* save to file */
  260. void save(char *fn)
  261.   {
  262.   unsigned int i,total=0;
  263.   FILE *f;
  264.   f=fopen(fn,"wb");
  265.   if (!f) { perror(fn); exit(1); }
  266. /* loop through entries */
  267.   for (i=0;i<last;i++)
  268.     {
  269. /* write size */
  270.     putc(phonelst[i].siz,f);
  271. /* write entry */
  272.     fwrite(phonelst[i].text,1,phonelst[i].siz,f);
  273. /* update total */
  274.     total+=phonelst[i].siz+1;
  275.     }
  276.   fclose(f);
  277.   printf("Saved %s (%u bytes)\n",fn,total);
  278.   }
  279.  
  280.  
  281.  
  282. /********************************************
  283. /* This routine deletes the character at p from a string.
  284.    As written, it knows that strcpy() moves characters
  285.    from lower addresses first -- behavior that might
  286.    not be true on all systems. That is why sdelete()
  287.    is a seperate function -- you may want to change it. */
  288. void sdelete(char *p)
  289.   {
  290.   strcpy(p,p+1);
  291.   }
  292.  
  293.  
  294. /********************************************
  295. /* replace an entry */
  296. void replace()
  297.   {
  298.   char ans[4];
  299.   while (1)
  300.     {
  301.     printf("Entry (? for list): ");
  302.     *ans='\0';
  303.     fgets(ans,sizeof(ans),stdin);
  304.     if (*ans=='\n') return;
  305. /* if ? print list */
  306.     if (*ans=='?')
  307.       {
  308.       list(stdout);
  309.       continue;
  310.       }
  311. /* call new to make entry */
  312.     new(atoi(ans));
  313.     break;
  314.     }
  315.   }
  316.  
  317.  
  318. /********************************************
  319. /* Find entries that match an entered substring */
  320. void find()
  321.   {
  322.   int i,len;
  323.   printf("Search for: ");
  324.   linein(inbuf,sizeof(inbuf),stdin);
  325.   if (!*inbuf) return;
  326.   len=strlen(inbuf);
  327. /* search for entry */
  328.   for (i=0;i<last;i++)
  329.     {
  330. /* decode */
  331.     b40_decode(cvtbuf,phonelst[i].text,phonelst[i].siz);
  332. /* only look at substring */
  333.     if (!strncmp(cvtbuf,inbuf,len))
  334.       disp(stdout,i,cvtbuf);    /* display matches */
  335.     }
  336.   }
  337.  
  338.  
  339. /********************************************
  340. /* Function to support qsort() */
  341. static int sortfunc(const void *in1,const void *in2)
  342.   {
  343. /* decode and compare */
  344.   struct phentry *e1, *e2;
  345.   e1=(struct phentry *)in1;
  346.   e2=(struct phentry *)in2;
  347.   b40_decode(cvtbuf,e1->text,e1->siz);
  348.   b40_decode(inbuf,e2->text,e2->siz);
  349.   return strcmp(cvtbuf,inbuf);
  350.   }
  351.  
  352.  
  353. /********************************************
  354. /* Sort function */
  355. void telsort()
  356.   {
  357.   qsort(phonelst,last,sizeof(phonelst[0]),sortfunc);
  358.   }
  359.